package net.intellect.collectpro.gestores;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.intellect.collectpro.util.Constantes;

import com.sforce.soap.enterprise.ID;
import com.sforce.soap.enterprise.sobject.Cobro__c;
import com.sforce.soap.enterprise.sobject.Pago__c;

/**
 * Class which holds the logic to update charges information, from a list of recent payments. 
 * @author Intellect International de Costa Rica, TRF
 * @since 05/19/09
 */
public class GestorBanco extends Pago implements GestorDePagos {
	
	/**
	 * Class constructor which invokes super class constructor.
	 * @param user Salesforce valid user.
	 * @param password Salesforce valid password.
	 * @param token Salesforce valid security token.
	 * @param codEmpresa Id from company for which payments are being processed.
	 */
	public GestorBanco(String user,String password,String token,String codEmpresa,String urlProxy,String puertoProxy) {
		this(user,password,token,codEmpresa,false,urlProxy,puertoProxy);		
	}

	/**
	 * Class constructor which invokes super class constructor.
	 * @param user Salesforce valid user.
	 * @param password Salesforce valid password.
	 * @param token Salesforce valid security token.
	 * @param codEmpresa Id from company for which payments are being processed.
	 * @param isSandBox true when we are working in a test environment, false if we are working against
	 * production servers. 
	 */
	public GestorBanco(String user,String password,String token,String codEmpresa,boolean isSandBox,String urlProxy,String puertoProxy) {
		super(user, password, token, codEmpresa,isSandBox,urlProxy,puertoProxy);
	}

	/**
	 * @author Gina
	 * Aplica los pagos a partir de la fecha indicada 
	 */
	public void aplicarPagos(ID empresaId, Date fecha) throws Exception {
		logger.debug("Dentro del gestor de pagos de banco");
		List<Cobro__c> cobros = new ArrayList<Cobro__c>();
		List<Pago__c> pagos = this.obtenerPagosBanco(empresaId, fecha);
		Map<String,Double> pagosMap = new HashMap<String,Double>();
		
		// Recorre la lista de pagos y los separa por cobros
		for (int i = 0; i < pagos.size(); i++) {
			Pago__c pago = (Pago__c)pagos.get(i);
			
			// Verifica que el cobro se haya consultado bien
		    if (pago.getCobro__c()!= null && pago.getCobro__r()!= null ) {
		    	//!Double.isNaN(pago.getCobro__r().getSaldo_exigible__c())) {
		    	
		    	// Verifica si ya existe una lista para el cobro del pago
				if (!pagosMap.containsKey(pago.getCobro__c().getID())) {
					Cobro__c cobro = new Cobro__c();
					
					cobro.setId(pago.getCobro__c());
					cobro.setPara_rehabilitaci_n__c(!Double.isNaN(pago.getCobro__r().getPara_rehabilitaci_n__c())?pago.getCobro__r().getPara_rehabilitaci_n__c():0);
					cobro.setPara_Contenci_n__c(!Double.isNaN(pago.getCobro__r().getPara_Contenci_n__c())?pago.getCobro__r().getPara_Contenci_n__c():0);
					cobro.setPara_Liberaci_n_4__c(!Double.isNaN(pago.getCobro__r().getPara_Liberaci_n_4__c())?pago.getCobro__r().getPara_Liberaci_n_4__c():0);
					cobro.setPara_Liberaci_n_3__c(!Double.isNaN(pago.getCobro__r().getPara_Liberaci_n_3__c())?pago.getCobro__r().getPara_Liberaci_n_3__c():0);
					cobro.setPara_Liberaci_n_2__c(!Double.isNaN(pago.getCobro__r().getPara_Liberaci_n_2__c())?pago.getCobro__r().getPara_Liberaci_n_2__c():0);
					cobro.setPara_Liberaci_n_1__c(!Double.isNaN(pago.getCobro__r().getPara_Liberaci_n_1__c())?pago.getCobro__r().getPara_Liberaci_n_1__c():0);
					cobros.add(cobro);
					
					pagosMap.put(cobro.getId().getID(), new Double(0));
				}

				Double saldo = pagosMap.get(pago.getCobro__c().getID());
				saldo += pago.getMonto__c();
				pagosMap.put(pago.getCobro__c().getID(), saldo);
		    }
		}
		
		// Checks the total payment to verify 
		List<Cobro__c> cobrosRehabilitar = new ArrayList<Cobro__c>();
		for(int i = 0; i < cobros.size(); i++) {
			Cobro__c ct = (Cobro__c)cobros.get(i);
			Double saldo = pagosMap.get(ct.getId().getID());
			
			if (saldo >= ct.getPara_rehabilitaci_n__c()) {
				
				if (ct.getPara_rehabilitaci_n__c() > 0){
					
					ct.setFecha_Rehabilitacion__c(new Date());
					ct.setEstado_Cobro__c(Constantes.COBRO_REHABILITADO);
					cobrosRehabilitar.add(ct);
				}
				
			} else if (ct.getPara_Liberaci_n_1__c() > 0 &&
				saldo >= ct.getPara_Liberaci_n_1__c()) {
				ct.setEstado_Cobro__c(Constantes.COBRO_NIVEL_I);
				cobrosRehabilitar.add(ct);
			
			} else if (ct.getPara_Liberaci_n_2__c() > 0 && 
				saldo >= ct.getPara_Liberaci_n_2__c()) {
				ct.setEstado_Cobro__c(Constantes.COBRO_NIVEL_II);
				cobrosRehabilitar.add(ct);
			
			} else if (ct.getPara_Liberaci_n_3__c() > 0 &&
				saldo >= ct.getPara_Liberaci_n_3__c()) {
				ct.setEstado_Cobro__c(Constantes.COBRO_NIVEL_III);
				cobrosRehabilitar.add(ct);
			
			} else if (ct.getPara_Liberaci_n_4__c() > 0 &&
				saldo >= ct.getPara_Liberaci_n_4__c()) {
				ct.setEstado_Cobro__c(Constantes.COBRO_NIVEL_IV);
				cobrosRehabilitar.add(ct);
			
			} else if (ct.getPara_Contenci_n__c() > 0 &&
				saldo >= ct.getPara_Contenci_n__c()){
				ct.setEstado_Cobro__c(Constantes.COBRO_CONTENIDO);
				cobrosRehabilitar.add(ct);
			}
			// Agrega el cobro para que pueda ser modificado en la db
			logger.debug("Cobro modificado: id[" + ct.getId().getID() + "] " +
					"Total pago[" + saldo + "] Nuevo estado[" + ct.getEstado_Cobro__c() + "] \n" +
					"Para rehabilitar: " + ct.getPara_rehabilitaci_n__c() + "\n" +
					"Para nivel 1: " + ct.getPara_Liberaci_n_1__c() + "\n" +
					"Para nivel 2: " + ct.getPara_Liberaci_n_2__c() + "\n" +
					"Para nivel 3: " + ct.getPara_Liberaci_n_3__c() + "\n" +
					"Para nivel 4: " + ct.getPara_Liberaci_n_4__c() + "\n" +
					"Para Contencion: " + ct.getPara_Contenci_n__c());
			// Actualiza DB
			
		}
		
		super.actualizarRegistros(cobrosRehabilitar);

	}

}
